{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Solving TSP with Deep Rerinforcement Learning#\n",
    "\n",
    "The notebook implements an improvement-base DRL method for solving the TSP problem by iteratively improving a feasible solution.\n",
    "\n",
    "The code is based on the following paper:\n",
    "\n",
    "```\n",
    "Wu, Y., Song, W., Cao, Z., Zhang, J. and Lim, A., 2019. Learning improvement heuristics for solving the travelling salesman problem.\n",
    "```(https://arxiv.org/abs/1912.05784)\n",
    "\n",
    "© National University of Singapore. All Rights Reserved."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Prepare: Install dependencies\n",
    "### Install with pip\n",
    "* PyTorch>=1.1\n",
    "* numpy\n",
    "* tqdm\n",
    "* cv2\n",
    "* tensorboard_logger\n",
    "* imageio (optional, for plots)\n",
    "\n",
    "### One more thing\n",
    "For the exception below from package tensorboard_logger,\n",
    "```python\n",
    "AttributeError: module 'scipy.misc' has no attribute 'toimage'\n",
    "```\n",
    "Please refer to [issue #27](https://github.com/TeamHG-Memex/tensorboard_logger/issues/27) to fix it."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [],
   "source": [
    "import os\n",
    "import json\n",
    "import pprint\n",
    "\n",
    "import torch\n",
    "import torch.optim as optim\n",
    "from tensorboard_logger import Logger as TbLogger\n",
    "from torch.utils.data import DataLoader\n",
    "\n",
    "from nets.critic_network import CriticNetwork\n",
    "from train import train_epoch, validate\n",
    "from nets.reinforce_baselines import CriticBaseline\n",
    "from nets.attention_model import AttentionModel\n",
    "from utils import torch_load_cpu, load_problem, get_inner_model, move_to\n",
    "from utils.plots import plot_tour\n",
    "\n",
    "import warnings\n",
    "warnings.filterwarnings(\"ignore\", category=Warning)\n",
    "os.environ['KMP_DUPLICATE_LIB_OK']='True'"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## load the settings for training\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [],
   "source": [
    "# load the run args\n",
    "%run options\n",
    "\n",
    "# Set the random seed\n",
    "torch.manual_seed(opts.seed)\n",
    "\n",
    "# Optionally configure tensorboard\n",
    "tb_logger = None\n",
    "if not opts.no_tensorboard:\n",
    "    tb_logger = TbLogger(os.path.join(opts.log_dir, \"{}_{}\".format(opts.problem, opts.graph_size), opts.run_name))\n",
    "\n",
    "if not os.path.exists(opts.save_dir):\n",
    "    os.makedirs(opts.save_dir)\n",
    "\n",
    "# Save arguments so exact configuration can always be found\n",
    "with open(os.path.join(opts.save_dir, \"args.json\"), 'w') as f:\n",
    "    json.dump(vars(opts), f, indent=True)\n",
    "\n",
    " # Set the device\n",
    "opts.device = torch.device(\"cuda\" if opts.use_cuda else \"cpu\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The default settings:\n",
    "```\n",
    "Runinig:\n",
    "    devices: GPU if avaliable else CPU\n",
    "    logging to tensorboard: True\n",
    "    logging figures: True\n",
    "    seed used: 1\n",
    "    \n",
    "Problem:\n",
    "    TSP size: 20 nodes\n",
    "    step method: 2-opt\n",
    "    checking feasibility for each step: True\n",
    "    \n",
    "network:\n",
    "    embedding_dim: 128\n",
    "    hidden_dim: 128\n",
    "    n_encoder_layers: 3\n",
    "    n_heads_encoder: 1\n",
    "    n_heads_decoder: 1\n",
    "    normalization: batch\n",
    "    \n",
    "training:\n",
    "    batch_size: 5120\n",
    "    epoch_size: 51200\n",
    "    number of epochs to train: 100\n",
    "    T_max: 200\n",
    "    n_step: 4\n",
    "    gamma: 0.99\n",
    "    learning_rate_init: 1e-4\n",
    "    learning_rate_decay: 0.99\n",
    "    \n",
    "validating:\n",
    "    dataset: './datasets/tsp_20_10000.pkl'\n",
    "    batch_size: 1000\n",
    "    T_max: 1000\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Simplify the training only for demonstration purpose\n",
    "Current setting requires GPUs for efficient learning.\n",
    "It takes around 8 hours on a single GeForce RTX 2080 Ti GPU card.\n",
    "\n",
    "We simplify the settings by reducing the batch size and the epoch size for demo purpose.\n",
    "\n",
    "Please skip this step for a real training."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Please skip this for a real training.\n",
    "opts.epoch_size = 32\n",
    "opts.batch_size = 16\n",
    "opts.val_size = 10\n",
    "opts.eval_batch_size = 10"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Figure out what's the problem"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "TSP with 20 nodes.\n"
     ]
    }
   ],
   "source": [
    "problem = load_problem(opts.problem)(\n",
    "                        p_size = opts.graph_size, # tsp size\n",
    "                        with_assert = not opts.no_assert) # if checking feasibiliy"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Initialize our policy network"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "AttentionModel(\n",
       "  (embedder): EmbeddingNet(\n",
       "    (embedder): Linear(in_features=2, out_features=128, bias=True)\n",
       "  )\n",
       "  (encoder): Sequential(\n",
       "    (0): MultiHeadAttentionLayer(\n",
       "      (0): SkipConnection(\n",
       "        (module): MultiHeadAttention()\n",
       "      )\n",
       "      (1): Normalization(\n",
       "        (normalizer): BatchNorm1d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
       "      )\n",
       "      (2): SkipConnection(\n",
       "        (module): Sequential(\n",
       "          (0): Linear(in_features=128, out_features=128, bias=True)\n",
       "          (1): ReLU()\n",
       "          (2): Linear(in_features=128, out_features=128, bias=True)\n",
       "        )\n",
       "      )\n",
       "      (3): Normalization(\n",
       "        (normalizer): BatchNorm1d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
       "      )\n",
       "    )\n",
       "    (1): MultiHeadAttentionLayer(\n",
       "      (0): SkipConnection(\n",
       "        (module): MultiHeadAttention()\n",
       "      )\n",
       "      (1): Normalization(\n",
       "        (normalizer): BatchNorm1d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
       "      )\n",
       "      (2): SkipConnection(\n",
       "        (module): Sequential(\n",
       "          (0): Linear(in_features=128, out_features=128, bias=True)\n",
       "          (1): ReLU()\n",
       "          (2): Linear(in_features=128, out_features=128, bias=True)\n",
       "        )\n",
       "      )\n",
       "      (3): Normalization(\n",
       "        (normalizer): BatchNorm1d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
       "      )\n",
       "    )\n",
       "    (2): MultiHeadAttentionLayer(\n",
       "      (0): SkipConnection(\n",
       "        (module): MultiHeadAttention()\n",
       "      )\n",
       "      (1): Normalization(\n",
       "        (normalizer): BatchNorm1d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
       "      )\n",
       "      (2): SkipConnection(\n",
       "        (module): Sequential(\n",
       "          (0): Linear(in_features=128, out_features=128, bias=True)\n",
       "          (1): ReLU()\n",
       "          (2): Linear(in_features=128, out_features=128, bias=True)\n",
       "        )\n",
       "      )\n",
       "      (3): Normalization(\n",
       "        (normalizer): BatchNorm1d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
       "      )\n",
       "    )\n",
       "  )\n",
       "  (project_graph): Linear(in_features=128, out_features=128, bias=False)\n",
       "  (project_node): Linear(in_features=128, out_features=128, bias=False)\n",
       "  (decoder): MultiHeadDecoder()\n",
       ")"
      ]
     },
     "execution_count": 20,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "model_class = {\n",
    "    'attention': AttentionModel,\n",
    "}.get(opts.model, None)\n",
    "assert model_class is not None, \"Unknown model: {}\".format(model_class)\n",
    "                                                           \n",
    "model = model_class(\n",
    "    problem = problem,\n",
    "    embedding_dim = opts.embedding_dim,\n",
    "    hidden_dim = opts.hidden_dim,\n",
    "    n_heads = 1, # can increase for better performance\n",
    "    n_layers = opts.n_encode_layers,\n",
    "    normalization = opts.normalization,\n",
    "    device = opts.device,\n",
    ").to(opts.device)\n",
    "\n",
    "if opts.use_cuda and torch.cuda.device_count() > 1:\n",
    "    model = torch.nn.DataParallel(model)\n",
    "    \n",
    "model"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Initialize our critic network"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "CriticNetwork(\n",
       "  (embedder): EmbeddingNet(\n",
       "    (embedder): Linear(in_features=2, out_features=128, bias=True)\n",
       "  )\n",
       "  (encoder): Sequential(\n",
       "    (0): MultiHeadAttentionLayer(\n",
       "      (0): SkipConnection(\n",
       "        (module): MultiHeadAttention()\n",
       "      )\n",
       "      (1): Normalization(\n",
       "        (normalizer): BatchNorm1d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
       "      )\n",
       "      (2): SkipConnection(\n",
       "        (module): Sequential(\n",
       "          (0): Linear(in_features=128, out_features=128, bias=True)\n",
       "          (1): ReLU()\n",
       "          (2): Linear(in_features=128, out_features=128, bias=True)\n",
       "        )\n",
       "      )\n",
       "      (3): Normalization(\n",
       "        (normalizer): BatchNorm1d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
       "      )\n",
       "    )\n",
       "    (1): MultiHeadAttentionLayer(\n",
       "      (0): SkipConnection(\n",
       "        (module): MultiHeadAttention()\n",
       "      )\n",
       "      (1): Normalization(\n",
       "        (normalizer): BatchNorm1d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
       "      )\n",
       "      (2): SkipConnection(\n",
       "        (module): Sequential(\n",
       "          (0): Linear(in_features=128, out_features=128, bias=True)\n",
       "          (1): ReLU()\n",
       "          (2): Linear(in_features=128, out_features=128, bias=True)\n",
       "        )\n",
       "      )\n",
       "      (3): Normalization(\n",
       "        (normalizer): BatchNorm1d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
       "      )\n",
       "    )\n",
       "    (2): MultiHeadAttentionLayer(\n",
       "      (0): SkipConnection(\n",
       "        (module): MultiHeadAttention()\n",
       "      )\n",
       "      (1): Normalization(\n",
       "        (normalizer): BatchNorm1d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
       "      )\n",
       "      (2): SkipConnection(\n",
       "        (module): Sequential(\n",
       "          (0): Linear(in_features=128, out_features=128, bias=True)\n",
       "          (1): ReLU()\n",
       "          (2): Linear(in_features=128, out_features=128, bias=True)\n",
       "        )\n",
       "      )\n",
       "      (3): Normalization(\n",
       "        (normalizer): BatchNorm1d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
       "      )\n",
       "    )\n",
       "  )\n",
       "  (project_graph): Linear(in_features=128, out_features=128, bias=False)\n",
       "  (project_node): Linear(in_features=128, out_features=128, bias=False)\n",
       "  (value_head): Sequential(\n",
       "    (0): Linear(in_features=128, out_features=128, bias=True)\n",
       "    (1): ReLU()\n",
       "    (2): Linear(in_features=128, out_features=1, bias=True)\n",
       "  )\n",
       ")"
      ]
     },
     "execution_count": 21,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "baseline = CriticBaseline(\n",
    "                CriticNetwork(\n",
    "                    problem = problem,\n",
    "                    embedding_dim = opts.embedding_dim,\n",
    "                    hidden_dim = opts.hidden_dim,\n",
    "                    n_heads = 1, # can increase for better performance\n",
    "                    n_layers = opts.n_encode_layers,\n",
    "                    normalization = opts.normalization,\n",
    "                    device = opts.device,\n",
    "                ).to(opts.device)\n",
    "        )\n",
    "baseline.critic"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    " ## Initialize the Adam optimizer and learning rate scheduler"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Adam (\n",
       "Parameter Group 0\n",
       "    amsgrad: False\n",
       "    betas: (0.9, 0.999)\n",
       "    eps: 1e-08\n",
       "    initial_lr: 0.0001\n",
       "    lr: 0.0001\n",
       "    weight_decay: 0\n",
       "\n",
       "Parameter Group 1\n",
       "    amsgrad: False\n",
       "    betas: (0.9, 0.999)\n",
       "    eps: 1e-08\n",
       "    initial_lr: 0.0001\n",
       "    lr: 0.0001\n",
       "    weight_decay: 0\n",
       ")"
      ]
     },
     "execution_count": 22,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Initialize optimizer\n",
    "optimizer = optim.Adam(\n",
    "            [{'params': model.parameters(), 'lr': opts.lr_model}]\n",
    "            + (\n",
    "                [{'params': baseline.get_learnable_parameters(), 'lr': opts.lr_critic}]\n",
    "                if len(baseline.get_learnable_parameters()) > 0 else []\n",
    "            )\n",
    "        )\n",
    "\n",
    "# Initialize learning rate scheduler, decay by lr_decay once per epoch!\n",
    "lr_scheduler = optim.lr_scheduler.LambdaLR(optimizer, lambda epoch: opts.lr_decay ** epoch)\n",
    "\n",
    "optimizer"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Load the validation datasets"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {},
   "outputs": [],
   "source": [
    "val_dataset = problem.make_dataset(size=opts.graph_size,\n",
    "                                   num_samples=opts.val_size,\n",
    "                                   filename = opts.val_dataset)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Start training !!\n",
    "\n",
    "Let's train 2 epochs with T=100 for example:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "\n",
      "\n",
      "| ********************* Training epoch 0 ********************* |\n",
      "Training with lr=1.000e-04 for run run_name_20200730T131309\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "training: 100%|████████████████████| 50/50 [00:21<00:00,  2.30it/s]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Saving model and state...\n",
      "\n",
      "Validating...\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "\n",
      "rollout: 100%|████████████████████| 1000/1000 [00:16<00:00, 59.43it/s]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      " ------------------------------------------------------------\n",
      "         Avg total reward:          4.241685   +- 0.332718  \n",
      "          Avg step reward:          0.004242   +- 0.018454  \n",
      "------------------------------------------------------------\n",
      "           Avg init cost:           9.923937   +- 0.394804  \n",
      "  Avg cost after 20% improvement:   7.812395   +- 0.356064  \n",
      "  Avg cost after 40% improvement:   8.460790   +- 0.438866  \n",
      "  Avg cost after 60% improvement:   7.955374   +- 0.452564  \n",
      "  Avg cost after 80% improvement:   7.949316   +- 0.383378  \n",
      "  Avg cost after 100% improvement:  7.953381   +- 0.340813  \n",
      "           Avg best cost:           5.682251   +- 0.208888  \n",
      "------------------------------------------------------------\n",
      "           Avg used time:           1.683686s\n",
      "------------------------------------------------------------ \n",
      "\n",
      "\n",
      "\n",
      "\n",
      "| ********************* Training epoch 1 ********************* |\n",
      "Training with lr=9.900e-05 for run run_name_20200730T131309\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "training: 100%|████████████████████| 50/50 [00:21<00:00,  2.35it/s]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Saving model and state...\n",
      "\n",
      "Validating...\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "\n",
      "rollout: 100%|████████████████████| 1000/1000 [00:16<00:00, 59.53it/s]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      " ------------------------------------------------------------\n",
      "         Avg total reward:          4.521887   +- 0.343700  \n",
      "          Avg step reward:          0.004522   +- 0.016911  \n",
      "------------------------------------------------------------\n",
      "           Avg init cost:           9.923937   +- 0.394804  \n",
      "  Avg cost after 20% improvement:   7.329743   +- 0.386100  \n",
      "  Avg cost after 40% improvement:   7.252641   +- 0.287185  \n",
      "  Avg cost after 60% improvement:   7.615552   +- 0.334616  \n",
      "  Avg cost after 80% improvement:   7.065089   +- 0.304543  \n",
      "  Avg cost after 100% improvement:  7.979433   +- 0.344634  \n",
      "           Avg best cost:           5.402050   +- 0.164046  \n",
      "------------------------------------------------------------\n",
      "           Avg used time:           1.680866s\n",
      "------------------------------------------------------------ \n",
      "\n"
     ]
    }
   ],
   "source": [
    "opts.T_train = 100\n",
    "opts.n_epochs = 2\n",
    "opts.epoch_start = 0\n",
    "\n",
    "for epoch in range(opts.epoch_start, opts.epoch_start + opts.n_epochs):\n",
    "    train_epoch(\n",
    "        problem,\n",
    "        model,\n",
    "        optimizer,\n",
    "        baseline,\n",
    "        lr_scheduler,\n",
    "        epoch,\n",
    "        val_dataset,\n",
    "        tb_logger,\n",
    "        opts\n",
    "    )"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## let's show the training logs with Tensorboard"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Reusing TensorBoard on port 6006 (pid 49468), started 0:14:53 ago. (Use '!kill 49468' to kill it.)"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "\n",
       "      <iframe id=\"tensorboard-frame-1c20e6935ec8d126\" width=\"100%\" height=\"800\" frameborder=\"0\">\n",
       "      </iframe>\n",
       "      <script>\n",
       "        (function() {\n",
       "          const frame = document.getElementById(\"tensorboard-frame-1c20e6935ec8d126\");\n",
       "          const url = new URL(\"/\", window.location);\n",
       "          url.port = 6006;\n",
       "          frame.src = url;\n",
       "        })();\n",
       "      </script>\n",
       "  "
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "logs_base_dir = os.path.join(os.getcwd(),'logs/tsp_20')\n",
    "\n",
    "%load_ext tensorboard\n",
    "%tensorboard --logdir {logs_base_dir}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Let's see what an actual training looks like"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "\n",
       "      <iframe id=\"tensorboard-frame-2573b81c9d198457\" width=\"100%\" height=\"800\" frameborder=\"0\">\n",
       "      </iframe>\n",
       "      <script>\n",
       "        (function() {\n",
       "          const frame = document.getElementById(\"tensorboard-frame-2573b81c9d198457\");\n",
       "          const url = new URL(\"/\", window.location);\n",
       "          url.port = 6007;\n",
       "          frame.src = url;\n",
       "        })();\n",
       "      </script>\n",
       "  "
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# start a new tensorboard\n",
    "logs_base_dir = os.path.join(os.getcwd(),'logs/pre_trained')\n",
    "%tensorboard --logdir {logs_base_dir}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## We can load the pre-trained model"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "  [*] Loading data from ./outputs/tsp_20/tsp_20200714T212735/epoch-99.pt\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "<All keys matched successfully>"
      ]
     },
     "execution_count": 25,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "opts.load_path = './outputs/tsp_20/tsp_20200714T212735/epoch-99.pt'\n",
    "\n",
    "# Load data from load_path\n",
    "load_data = {}\n",
    "assert opts.load_path is None or opts.resume is None, \"Only one of load path and resume can be given\"\n",
    "load_path = opts.load_path if opts.load_path is not None else opts.resume\n",
    "if load_path is not None:\n",
    "    print('  [*] Loading data from {}'.format(load_path))\n",
    "    load_data = torch_load_cpu(load_path)\n",
    "\n",
    "# Overwrite model parameters by parameters to load\n",
    "model_ = get_inner_model(model)\n",
    "model_.load_state_dict({**model_.state_dict(), **load_data.get('model', {})})"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Validate using the loaded model"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "Validating...\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "rollout: 100%|████████████████████| 1000/1000 [00:15<00:00, 63.47it/s]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      " ------------------------------------------------------------\n",
      "         Avg total reward:          6.164712   +- 0.377554  \n",
      "          Avg step reward:          0.006165   +- 0.019763  \n",
      "------------------------------------------------------------\n",
      "           Avg init cost:           9.923937   +- 0.394804  \n",
      "  Avg cost after 20% improvement:   4.049284   +- 0.118281  \n",
      "  Avg cost after 40% improvement:   3.942811   +- 0.109086  \n",
      "  Avg cost after 60% improvement:   3.923949   +- 0.087778  \n",
      "  Avg cost after 80% improvement:   4.093946   +- 0.136721  \n",
      "  Avg cost after 100% improvement:  3.957371   +- 0.091912  \n",
      "           Avg best cost:           3.759225   +- 0.084913  \n",
      "------------------------------------------------------------\n",
      "           Avg used time:           1.576713s\n",
      "------------------------------------------------------------ \n",
      "\n"
     ]
    }
   ],
   "source": [
    "validate(problem, model, val_dataset, tb_logger, opts)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Let's look inside the model\n",
    "\n",
    "Let's see what happens when solving a particular TSP instance.\n",
    "### Get one TSP instance"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "tensor([[[0.4509, 0.8512],\n",
       "         [0.3281, 0.4170],\n",
       "         [0.2536, 0.4560],\n",
       "         [0.6566, 0.6865],\n",
       "         [0.0264, 0.5931],\n",
       "         [0.2647, 0.8877],\n",
       "         [0.9084, 0.8208],\n",
       "         [0.3501, 0.1872],\n",
       "         [0.9299, 0.0127],\n",
       "         [0.1770, 0.8813],\n",
       "         [0.1611, 0.9836],\n",
       "         [0.6462, 0.2009],\n",
       "         [0.5012, 0.6662],\n",
       "         [0.4446, 0.8552],\n",
       "         [0.5352, 0.5726],\n",
       "         [0.9432, 0.0668],\n",
       "         [0.6561, 0.2709],\n",
       "         [0.7097, 0.8725],\n",
       "         [0.6250, 0.1875],\n",
       "         [0.6853, 0.0979]]])"
      ]
     },
     "execution_count": 27,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "instance = next(iter(DataLoader(val_dataset, batch_size = 1)))\n",
    "instance"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Get one initial solution"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(tensor([[ 0.,  1.,  2.,  3.,  4.,  5.,  6.,  7.,  8.,  9., 10., 11., 12., 13.,\n",
       "          14., 15., 16., 17., 18., 19.]]),\n",
       " tensor([10.4616]))"
      ]
     },
     "execution_count": 33,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "solution = move_to(\n",
    "        problem.get_initial_solutions('seq', instance), opts.device)\n",
    "\n",
    "cost = problem.get_costs(instance, solution)\n",
    "\n",
    "solution, cost"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Plot the initial solution\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 576x432 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "plot_tour(solution, instance[0])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Pass through embedder only \n",
    "\n",
    "To show how embedder works, <br>\n",
    "we can pass the instance and the tour through only the embedder of our policy network, <br>\n",
    "and visualize the tour in the embedded space using PCA."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/plain": [
       "tensor([[ 0.,  1.,  2.,  3.,  4.,  5.,  6.,  7.,  8.,  9., 10., 11., 12., 13.,\n",
       "         14., 15., 16., 17., 18., 19.]])"
      ]
     },
     "execution_count": 30,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# the embedded input x\n",
    "bs, gs, in_d = instance.size()\n",
    "\n",
    "# pass through embedder: current solutions\n",
    "x_embed = model.embedder(instance, solution)\n",
    "\n",
    "# transform the high-dimensional data into two dimensions using PCA\n",
    "from sklearn.decomposition import PCA\n",
    "X = x_embed[0].detach().numpy()\n",
    "pca = PCA(n_components=2)\n",
    "pca.fit(X)\n",
    "out = pca.transform(X)\n",
    "\n",
    "# visualize the tour in the embedded space\n",
    "import matplotlib.pyplot as plt\n",
    "fig, ax = plt.subplots()\n",
    "for i in range(20):\n",
    "    ax.scatter(out[i,0], out[i,1])\n",
    "    plt.annotate(i+1,(out[i,0] - 0.015, out[i,1] - 0.06), fontsize=12) \n",
    "ax.grid(True)\n",
    "\n",
    "plt.show()\n",
    "solution"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Pass through encoder and decoder"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 2 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# pass through encoder: current solutions\n",
    "h_em = model.encoder(x_embed) # torch.Size([2, 50, 128])\n",
    "\n",
    "# get embed graph feature\n",
    "max_pooling = h_em.max(1)[0] # max Pooling\n",
    "graph_feature = model.project_graph(max_pooling)[:, None, :]\n",
    "\n",
    "# get embed node feature\n",
    "node_feature = model.project_node(h_em)\n",
    "\n",
    "# pass through decoder, get log_likelihood and M matrix\n",
    "fusion = node_feature + graph_feature.expand_as(node_feature) # torch.Size([2, 50, 128])\n",
    "log_likelihood, M_value = model.decoder(fusion, None, solution) # att torch.Size([1, 2, 2500])          \n",
    "\n",
    "# get the action table\n",
    "M_value = M_value.detach().view(20,20)\n",
    "M_value[problem.get_swap_mask(solution)[0].view(-1).view(20,20).bool()] = 0\n",
    "\n",
    "# visulize the action table\n",
    "import seaborn as sns; sns.set() \n",
    "sns.heatmap(M_value)\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# After we get this table, we can sample an action for the next step.\n",
    "\n",
    "### Solve this instance by rollout (T = 100)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "rollout: 100%|████████████████████| 100/100 [00:01<00:00, 73.61it/s]\n"
     ]
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 576x432 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/plain": [
       "(tensor([16.,  7.,  1.,  2.,  4.,  9., 10.,  5., 13.,  0., 12., 14.,  3., 17.,\n",
       "          6., 15.,  8., 19., 18., 11.]),\n",
       " tensor([[3.7876]]))"
      ]
     },
     "execution_count": 34,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from train import rollout\n",
    "x_input = move_to(instance, opts.device) # batch_size, graph_size, 2\n",
    "batch = move_to(instance, opts.device) # batch_size, graph_size, 2\n",
    "\n",
    "model.eval() # change to eval mode\n",
    "best_val, improvement, reward, history_solutions = rollout( problem, \n",
    "                                                             model, \n",
    "                                                             x_input, \n",
    "                                                             instance, \n",
    "                                                             solution, \n",
    "                                                             cost, \n",
    "                                                             opts, \n",
    "                                                             100,\n",
    "                                                             True,\n",
    "                                                             True)\n",
    "\n",
    "best_solution = history_solutions[0][-1,:]\n",
    "plot_tour(best_solution, instance[0])\n",
    "\n",
    "best_solution, best_val"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Visualize the improvement process"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "\n",
      "tour completed: 100%|██████████| 101/101 [00:14<00:00,  6.79it/s]A\n",
      "\n",
      "record for each instance: 100%|██████████| 1/1 [00:14<00:00, 14.88s/it]\u001b[A\n"
     ]
    }
   ],
   "source": [
    "from utils.record_a_video import record_gif\n",
    "record_gif(instance, history_solutions, filename = 'ep_gif', dpi = 60)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<img src=\"outputs/ep_gif_0.gif\">"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "execution_count": 30,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from IPython.display import HTML\n",
    "HTML('<img src=\"outputs/ep_gif_0.gif\">')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Any Questions?"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3.7.7 64-bit ('sac': conda)",
   "language": "python",
   "name": "python37764bitsaccondaf083af305ab2400da4d83aa9958e7a93"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.7"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
